const http = require("http");
const WebSocket = require("ws");

const CONFIG = {
    server: { host: "localhost", port: 3000, protocol: "http" },
    testUser: { mobile: "17091279999", passwordHash: "e10adc3949ba59abbe56e057f20f883e" },
};

function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }

function httpRequest(path, method = "GET", body = null) {
    const options = { hostname: CONFIG.server.host, port: CONFIG.server.port, path, method, headers: { "Content-Type": "application/json" } };
    return new Promise((resolve, reject) => {
        const req = http.request(options, (res) => {
            let data = "";
            res.on("data", (chunk) => (data += chunk));
            res.on("end", () => {
                try { const json = JSON.parse(data || "{}"); if (res.statusCode >= 200 && res.statusCode < 300) resolve(json); else reject(new Error(json?.msg || `HTTP ${res.statusCode}`)); } catch (e) { reject(new Error("响应解析失败")); }
            });
        });
        req.on("error", (err) => reject(err));
        if (body) req.write(JSON.stringify(body));
        req.end();
    });
}

async function ensureUserAndLogin() {
    try { await httpRequest("/user-service/user/register", "POST", { mobile: CONFIG.testUser.mobile, pwd: CONFIG.testUser.passwordHash, captcha: "123456" }); } catch { }
    const login = await httpRequest("/user-service/user/login", "POST", { mobile: CONFIG.testUser.mobile, pwd: CONFIG.testUser.passwordHash });
    if (login?.code !== 0) throw new Error(login?.msg || "登录失败");
    return { token: login.data.accessToken };
}

async function sendAndWait(ws, actId, payload = {}, timeoutMs = 10000) {
    return new Promise((resolve, reject) => {
        const timer = setTimeout(() => { ws?.off?.("message", handler); reject(new Error(`等待 act_id=${actId} 响应超时`)); }, timeoutMs);
        const handler = (raw) => {
            try { const msg = JSON.parse(raw.toString()); if (msg && msg.act_id === actId) { clearTimeout(timer); ws.off("message", handler); resolve(msg); } } catch { }
        };
        ws.on("message", handler);
        ws.send(JSON.stringify({ c: actId, d: Object.keys(payload).length ? payload : null }));
    });
}

(async () => {
    try {
        const { token } = await ensureUserAndLogin();
        const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${token}`;
        console.log("→ 连接WS:", wsUrl);
        const ws = new WebSocket(wsUrl);
        await new Promise((r, j) => { ws.on("open", r); ws.on("error", j); setTimeout(() => j(new Error("WS连接超时")), 12000); });
        console.log("✅ WS connected");

        // 获取角色列表
        console.log("→ 请求角色列表(3)");
        const list = await sendAndWait(ws, 3, {});
        let roleId = list?.roleList?.[0]?.id;
        if (!roleId) {
            console.log("→ 无角色，创建角色(5)");
            ws.send(JSON.stringify({ c: 5, d: { name: "房屋测试2", sex: 1, roleType: 1, headIndex: 2 } }));
            await sleep(800);
            const list2 = await sendAndWait(ws, 3, {});
            roleId = list2?.roleList?.[0]?.id;
        }
        if (!roleId) throw new Error("未能获取或创建角色");

        // 选择角色
        console.log("→ 选择角色(4)");
        await sendAndWait(ws, 4, { characterId: roleId });

        // 先查询 1480
        console.log("→ 查询 1480");
        let res = await sendAndWait(ws, 1480, {});
        console.log("1480:", JSON.stringify(res));

        // 购买 1385
        console.log("→ 购买 1385");
        const buy = await sendAndWait(ws, 1385, {});
        console.log("1385:", JSON.stringify(buy));

        // 再查 1480
        res = await sendAndWait(ws, 1480, {});
        console.log("1480-after-buy:", JSON.stringify(res));

        // 升级 1386
        console.log("→ 升级 1386");
        const up = await sendAndWait(ws, 1386, {});
        console.log("1386:", JSON.stringify(up));

        // 再查 1480
        res = await sendAndWait(ws, 1480, {});
        console.log("1480-after-up:", JSON.stringify(res));

        ws.close();
        console.log("✅ 测试完成");
    } catch (e) {
        console.error("❌ 自动测试失败:", e.message || e);
        process.exit(1);
    }
})();


